package com.ayu.shortlink.admin.service.basics.filter;

import cn.hutool.core.collection.CollUtil;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 创建优惠券模版基础责任链模版
 */
@Component
public final class AbstractVerifyFilterChainContext<T> implements ApplicationContextAware, CommandLineRunner{
    /**
     * IOC 容器
     */
    private ApplicationContext applicationContext;

    private final Map<String, List<AbstractVerifyFilterChainHandler>> abstractChainContainer = new HashMap<>();
    /**
     * 该方法由 ApplicationContextAware 提供
     * 目的是为了注入 IOC 容器
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 责任链校验执行
     */
    public void handler(String mark, T requestParam) {
        // 根据 mark 标识从责任链容器中获取一组责任链实现 Bean 集合
        List<AbstractVerifyFilterChainHandler> abstractChainHandlers = abstractChainContainer.get(mark);
        if (CollectionUtils.isEmpty(abstractChainHandlers)) {
            throw new RuntimeException(String.format("[%s] Chain of Responsibility ID is undefined.", mark));
        }
        abstractChainHandlers.forEach(each -> each.handler(requestParam));
    }

    /**
     * 该方法由 CommandLineRunner 提供， run 方法会在 SpringBoot 启动后运行
     */
    @Override
    public void run(String... args) throws Exception {
        Map<String, AbstractVerifyFilterChainHandler> chainHandlerMap = applicationContext.getBeansOfType(AbstractVerifyFilterChainHandler.class);

        chainHandlerMap.forEach((beanName,bean) -> {
            List<AbstractVerifyFilterChainHandler> abstractVerifyFilterChainHandlers = abstractChainContainer.get(bean.mark());
            //若没有则进行初始化
            if(CollUtil.isEmpty(abstractVerifyFilterChainHandlers)){
                abstractVerifyFilterChainHandlers = new ArrayList<>();
            }
            abstractVerifyFilterChainHandlers.add(bean);
            abstractChainContainer.put(bean.mark(),abstractVerifyFilterChainHandlers);
        });
        abstractChainContainer.forEach((mark,unsortedChainHandlers) -> {
            // 对每个 Mark 对应的责任链实现类集合进行排序，优先级小的在前
            unsortedChainHandlers.sort(Comparator.comparing(Ordered::getOrder));
        });
    }
}
